package net.sf.nlp.segment;

import java.util.ArrayList;
import java.util.List;

import net.sf.nlp.segment.util.StringUtility;

public class Sentence 
{
	private String sentence; 
	private List<AtomicWord> atomicWords;
	
	public Sentence(String sentence, List<AtomicWord> atomicWords)
	{
		this.sentence = sentence;
		this.atomicWords = atomicWords;
	}
	
	public String getSentence() {
		return sentence;
	}

	public void setSentence(String sentence) {
		this.sentence = sentence;
	}

	public List<AtomicWord> getAtomicWords() {
		return atomicWords;
	}

	public void setAtomicWords(List<AtomicWord> atomicWords) {
		this.atomicWords = atomicWords;
	}

	public static List<Sentence> normalization(String text)
	{
		List<Sentence> sentences = new ArrayList<Sentence>();
		
		if (text == null)
			return sentences;
		
		text = text.trim();
		StringBuffer sb = new StringBuffer();
		List<AtomicWord> atomicWords = new ArrayList<AtomicWord>();
		AtomicWord atomicWord = null;
		int atomicWordIndex = 1;
		
		for (int i = 0; i < text.length(); i++)
		{
			String ch = String.valueOf(text.charAt(i));
			
			sb.append(ch);
			
			if (StringUtility.isBlank(ch))
			{
				if (atomicWord != null)
				{
					atomicWords.add(atomicWord.clone());
					atomicWord = null;
				}
				continue;
			}
			
			if (StringUtility.isChineseWord(ch))
			{
				if (atomicWord != null)
				{
					atomicWords.add(atomicWord.clone());
					atomicWord = null;
				}
				
				atomicWords.add(new AtomicWord(atomicWordIndex++, ch, true));
			}
			else
			{
				if (atomicWord == null)
					atomicWord = new AtomicWord(atomicWordIndex++, null, false);
				
				if (atomicWord.isChinese())
				{
					atomicWords.add(atomicWord.clone());
					atomicWord = new AtomicWord(atomicWordIndex++, ch, false);
				}
				else
				{
					atomicWord.append(ch);
				}
			}
			
			Sentence sentence = generateSentence(sb, ch, atomicWord, atomicWords);
			
			if (sentence != null)
			{
				sb.delete(0, sb.length());
				atomicWord = null;
				atomicWords.clear();
				atomicWordIndex = 1;
				sentences.add(sentence);
			}
		}
		
		if (atomicWord != null)
			atomicWords.add(atomicWord.clone());
		
		Sentence sentence = generateSentence(sb, "\r\n", null, atomicWords);
		if (sentence != null)
			sentences.add(sentence);
		
		return sentences;
	}
	
	private static Sentence generateSentence(StringBuffer sb, String ch, AtomicWord atomicWord, List<AtomicWord> atomicWords)
	{
		if (sb.length() == 0)
			return null;
		
		if (StringUtility.isSentenceSeparator(ch))
		{
			sb.insert(0, StringUtility.SENTENCE_BEGIN).append(StringUtility.SENTENCE_END);
			
			if (atomicWord != null)
				atomicWords.add(atomicWord);
			
			List<AtomicWord> aw = new ArrayList<AtomicWord>();
			aw.addAll(atomicWords);
			aw.add(0, new AtomicWord(0, StringUtility.SENTENCE_BEGIN, true));
			aw.add(new AtomicWord(aw.size(), StringUtility.SENTENCE_END, true));
			
			return new Sentence(sb.toString(), aw);
		}
		
		return null;
	}
	
	public SegGraph generateSegmentNode(Dictionary coreDict, Dictionary relationDict, int bestN)
	{
		if (atomicWords == null)
			return null;
		
		List<SegNode> segNodes = new ArrayList<SegNode>();
		StringBuffer sb = new StringBuffer();
		SegNode segNode = null;
		TrieTreeNode node;
		List<WordItem> wordItems = null;
		
		for (int i = 0; i < atomicWords.size(); i++)
		{
			AtomicWord firstAtomicWord = atomicWords.get(i);
			//sb.append(firstAtomicWord.getAliasWord());
			
			segNode = new SegNode();
			segNode.setAtomicWords(atomicWords.subList(i, i + 1));
			//wordItems = coreDict.getWordItems(segNode.getAliasNodeWord());
			node = getNodeFromCoreDict(coreDict, sb, segNode);
			if (node != null)
			{
				segNode.setWordItems(node.getWordItems());
				segNode.setCustomized(node.isCustomized());
			}
			segNode.setValue(getTotalFreq(wordItems));
			
			segNodes.add(segNode);
			
			segNode.setPosType(getPosType(firstAtomicWord));
			
			for (int j = i + 1; j < atomicWords.size(); j++)
			{
				AtomicWord appendAtomicWord = atomicWords.get(j);
				
				//sb.append(appendAtomicWord.getAliasWord());
				
				node = getNodeFromCoreDict(coreDict, sb, appendAtomicWord);
				if (node == null)
					break;
				
				wordItems = node.getWordItems();
				if (wordItems == null || wordItems.size() == 0)
					continue;
				
				segNode = new SegNode();
				segNode.setAtomicWords(atomicWords.subList(i, j + 1));
				wordItems = coreDict.getWordItems(segNode.getAliasNodeWord());
				segNode.setWordItems(wordItems);
				segNode.setCustomized(node.isCustomized());
				segNode.setValue(getTotalFreq(wordItems));
				segNodes.add(segNode);
			}
			
			sb.delete(0, sb.length());
		}
		
		SegGraph segGraph = new SegGraph(relationDict, atomicWords, segNodes, bestN);
		
		return segGraph;
	}
	
	private TrieTreeNode getNodeFromCoreDict(Dictionary coreDict, StringBuffer sb, SegNode segNode)
	{
		TrieTreeNode node = coreDict.getTrieTreeNode(segNode.getNodeWord());
		
		if (node != null)
		{
			sb.append(segNode.getNodeWord());
			return node;
		}
		
		sb.append(segNode.getAliasNodeWord());
		return coreDict.getTrieTreeNode(segNode.getAliasNodeWord());
	}
	
	private TrieTreeNode getNodeFromCoreDict(Dictionary coreDict, StringBuffer sb, AtomicWord atomicWord)
	{
		sb.append(atomicWord.getAtomicWord());
		
		TrieTreeNode node = coreDict.getTrieTreeNode(sb.toString());
		
		if (node != null)
			return node;
		
		int length = sb.length();
		
		sb.delete(length - atomicWord.getAtomicWord().length(), length);
		sb.append(atomicWord.getAliasWord());
		
		return coreDict.getTrieTreeNode(sb.toString());
	}
	
	private PosType getPosType(AtomicWord atomicWord)
	{
		if (StringUtility.isSentenceSeparator(atomicWord.getAtomicWord()))
			return PosType.PUNC;
		
		if (atomicWord.isNumber())
			return PosType.NUM;
		else if (atomicWord.isChinese())
			return null;
		
		return PosType.UNKNOWN;
	}
	
	private double getTotalFreq(List<WordItem> wordItems)
	{
		double freq = 0;
		if (wordItems == null)
			return freq;
		
		for (WordItem wordItem : wordItems)
			freq = freq + wordItem.getFreq();
		
		return freq;	
	}
	
	public static void main(String[] args)
	{
		Sentence.normalization("许文强生于1943年6月28日,. csdn aa死于1978年。 ");
	}
}
